﻿using Batman.DLL.UserModule;
using Batman.DLL.UserModule.Models;
using Batman.DLL.UserModule.Models.Weixin;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Batman.IdentityServer.Weixin.Consts;

namespace Batman.BLL.UserModule.WeixinResource
{
    public class WeiXinOpenGrantValidator : IExtensionGrantValidator
    {
        public string GrantType => GrantTypeConstants.WeixinOpen;

        readonly IServiceScopeFactory _serviceScopeFactory;

        private UserManager<User> _userManager;

        public WeiXinOpenGrantValidator(IServiceScopeFactory serviceScopeFactory, UserManager<User> userManager)
        {
            _serviceScopeFactory = serviceScopeFactory;
            _userManager = userManager;
        }

        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            try
            {
                #region 参数获取
                var openId = context.Request.Raw[ParamConstants.OpenId];
                var unionId = context.Request.Raw[ParamConstants.UnionId];
                var userName = context.Request.Raw[ParamConstants.UserName];
                #endregion

                #region 通过openId和unionId 参数来进行数据库的相关验证
                var claimList = await ValidateUserAsync(openId, unionId);
                #endregion

                #region 授权通过
                //授权通过返回
                context.Result = new GrantValidationResult
                (
                    subject: claimList.FirstOrDefault(t => t.Type == ClaimTypes.Name)?.Value,
                    authenticationMethod: "custom",
                    claims: claimList.ToArray()
                );
                #endregion
            }
            catch (Exception ex)
            {
                context.Result = new GrantValidationResult()
                {
                    IsError = true,
                    Error = ex.Message
                };
            }
        }

        #region Private Method
        /// <summary>
        /// 验证用户
        /// </summary>
        /// <returns></returns>
        private async Task<List<Claim>> ValidateUserAsync(string openId, string unionId)
        {
            using (var serviceScope = _serviceScopeFactory.CreateScope())
            {
                var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

                var account = await context.WexinAccount.AsNoTracking().FirstOrDefaultAsync(t => t.OpenId == openId);

                if (account == null)
                {
                    User user = new User()
                    {
                        UserName = Guid.NewGuid().ToString(),
                    };
                    user.PasswordHash = _userManager.PasswordHasher.HashPassword(user, Guid.NewGuid().ToString());
                    var createResult = await _userManager.CreateAsync(user);
                    account = new WeixinAccount
                    {
                        OpenId = openId,
                        CreateAt = DateTime.Now,
                        Name = string.Empty,
                        UnionId = unionId,
                        UserId = user.Id
                    };
                    await context.WexinAccount.AddAsync(account);
                    await context.SaveChangesAsync();
                }
                return new List<Claim>()
                {
                    new Claim(ClaimTypes.Name, $"{account.UserId}"),
                    new Claim("OpenId", $"{account.OpenId}"),
                };
            }
        }

        #endregion
    }
}
